package com.lan.utils.tree;

import com.lan.entity.Entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  树形构造器
 * </p>
 *
 * @author shadow
 * @since 2022-09-26
 */
public class TreeBuilder {

    private static final Logger logger = LoggerFactory.getLogger(TreeBuilder.class);

    public TreeBuilder() {
    }

    public static <T extends Entity> List<TreeNode<T>> createTree(List<T> list, List<T> checkedList, String topParentId) {
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, List<TreeNode<T>>> map = new HashMap<>();
        for (T t : list) {
            TreeNode<T> child = objectToTree(t);
            if (null != child) {
                if (null != checkedList && !checkedList.isEmpty()
                        && checkedList.stream().anyMatch(c -> c.getId().equals(t.getId()))) {
                    child.setChecked(Boolean.TRUE);
                }
                String parentId = child.getParentId();
                if (null != parentId && map.containsKey(parentId)) {
                    map.get(parentId).add(child);
                } else {
                    List<TreeNode<T>> childrenList = new ArrayList<>();
                    childrenList.add(child);
                    map.put(parentId, childrenList);
                }
            }
        }
        // 顶级
        List<TreeNode<T>> topList = map.get(topParentId);
        List<Integer> sum = new ArrayList<>();
        if (!topList.isEmpty()) {
            map.remove(topParentId);
            int level = 2;
            while (map.size() > sum.size()) {
                boolean flag = false;
                // 二级
                for (TreeNode<T> topMenu : topList) {
                    if (level == 2) {
                        map.forEach((key, value) -> {
                            if (topMenu.getId().equals(key)) {
                                topMenu.setChildren(value);
                                sum.add(2);
                            }
                        });
                    } else if (level == 3) {
                        List<TreeNode<T>> childrenList = topMenu.getChildren();
                        if (childrenList.isEmpty()) continue;
                        childrenList.forEach(children -> map.forEach((key, value) -> {
                            if (children.getId().equals(key)) {
                                children.setChildren(value);
                                sum.add(3);
                            }
                        }));
                    } else {
                        logger.error("<<<<<<<<<< tree error >>>>>>>>>> out of map : {}", map);
                        flag = true;
                    }
                }
                if (flag) break;
                level++;
            }
        }
        return topList;
    }

    private static <T> TreeNode<T> objectToTree(final T object) {
        try {
            Method toTreeMethod = object.getClass().getMethod("toTree");
            return (TreeNode<T>) toTreeMethod.invoke(object);
        } catch (SecurityException e) {
            logger.error("获取toTree方法SecurityException异常", e);
        } catch (NoSuchMethodException e) {
            logger.error("获取toTree方法NoSuchMethodException异常", e);
        } catch (IllegalArgumentException e) {
            logger.error("调用toTree方法IllegalArgumentException异常", e);
        } catch (IllegalAccessException e) {
            logger.error("调用toTree方法IllegalAccessException异常", e);
        } catch (InvocationTargetException e) {
            logger.error("调用toTree方法InvocationTargetException异常", e);
        }
        return null;
    }

}
